import { executionModel, scriptModel, connectionModel, type IExecution, type ExecutionStats } from '../database/models';

export interface ExecuteScriptData {
  script_id: string;
  connection_id: string;
  executed_by?: string;
}

export interface ExecutionHistoryOptions {
  script_id?: string;
  connection_id?: string;
  status?: 'running' | 'completed' | 'failed' | 'cancelled';
  executed_by?: string;
  start_date?: Date;
  end_date?: Date;
  limit?: number;
  offset?: number;
}

export class ExecutionService {
  // 开始执行脚本
  async startExecution(data: ExecuteScriptData): Promise<IExecution> {
    // 验证脚本是否存在
    const script = await scriptModel.findById(data.script_id);
    if (!script) {
      throw new Error('脚本不存在');
    }
    
    if (!script.content || script.content.trim() === '') {
      throw new Error('脚本内容为空，无法执行');
    }
    
    // 验证连接是否存在且可用
    const connection = await connectionModel.getConnectionById(data.connection_id);
    if (!connection) {
      throw new Error('数据库连接不存在');
    }
    
    if (!connection.is_active) {
      throw new Error('数据库连接已禁用');
    }
    
    // 创建执行记录
    return await executionModel.createExecution({
      script_id: data.script_id,
      connection_id: data.connection_id,
      ...(data.executed_by && { executed_by: data.executed_by })
    });
  }
  
  // 完成执行
  async completeExecution(executionId: string, data: {
    rows_affected?: number;
    execution_plan?: string;
    result_preview?: any;
  }): Promise<IExecution | null> {
    const execution = await executionModel.findById(executionId);
    if (!execution) {
      throw new Error('执行记录不存在');
    }
    
    if (execution.status !== 'running') {
      throw new Error('执行已结束，无法更新状态');
    }
    
    return await executionModel.completeExecution(executionId, data);
  }
  
  // 执行失败
  async failExecution(executionId: string, errorMessage: string): Promise<IExecution | null> {
    const execution = await executionModel.findById(executionId);
    if (!execution) {
      throw new Error('执行记录不存在');
    }
    
    if (execution.status !== 'running') {
      throw new Error('执行已结束，无法更新状态');
    }
    
    return await executionModel.failExecution(executionId, errorMessage);
  }
  
  // 取消执行
  async cancelExecution(executionId: string): Promise<IExecution | null> {
    const execution = await executionModel.findById(executionId);
    if (!execution) {
      throw new Error('执行记录不存在');
    }
    
    if (execution.status !== 'running') {
      throw new Error('只能取消正在运行的执行');
    }
    
    return await executionModel.cancelExecution(executionId);
  }
  
  // 获取执行详情
  async getExecution(executionId: string): Promise<IExecution | null> {
    return await executionModel.findById(executionId);
  }
  
  // 获取执行历史
  async getExecutionHistory(options: ExecutionHistoryOptions = {}): Promise<{
    executions: IExecution[];
    total: number;
    page: number;
    pageSize: number;
    totalPages: number;
  }> {
    const limit = options.limit || 20;
    const offset = options.offset || 0;
    const page = Math.floor(offset / limit) + 1;
    
    let executions: IExecution[] = [];
    let total = 0;
    
    if (options.script_id) {
      // 获取特定脚本的执行历史
      const result = await executionModel.getExecutionHistory(options.script_id, {
        limit,
        offset,
        status: options.status,
        connection_id: options.connection_id,
        executed_by: options.executed_by
      });
      executions = result.executions;
      total = result.total;
    } else if (options.connection_id) {
      // 获取特定连接的执行历史
      const result = await executionModel.getExecutionsByConnection(options.connection_id, {
        limit,
        offset,
        status: options.status
      });
      executions = result.executions;
      total = result.total;
    } else {
      // 获取所有执行历史
      const whereConditions: any = {};
      if (options.status) whereConditions.status = options.status;
      if (options.executed_by) whereConditions.executed_by = options.executed_by;
      
      executions = await executionModel.findAll({
        where: whereConditions,
        limit,
        offset,
        orderBy: 'start_time',
        orderDirection: 'DESC'
      });
      
      total = await executionModel.count(whereConditions);
    }
    
    // 如果有日期过滤，需要额外处理
    if (options.start_date || options.end_date) {
      executions = executions.filter(execution => {
        if (options.start_date && execution.start_time < options.start_date) {
          return false;
        }
        if (options.end_date && execution.start_time > options.end_date) {
          return false;
        }
        return true;
      });
    }
    
    const totalPages = Math.ceil(total / limit);
    
    return {
      executions,
      total,
      page,
      pageSize: limit,
      totalPages
    };
  }
  
  // 获取正在运行的执行
  async getRunningExecutions(): Promise<IExecution[]> {
    return await executionModel.getRunningExecutions();
  }
  
  // 获取执行统计
  async getExecutionStats(options: {
    script_id?: string;
    connection_id?: string;
    executed_by?: string;
    start_date?: Date;
    end_date?: Date;
  } = {}): Promise<ExecutionStats & {
    success_rate: number;
    avg_duration_formatted: string;
  }> {
    const stats = await executionModel.getExecutionStats(options);
    
    const success_rate = stats.total_executions > 0 
      ? (stats.successful_executions / stats.total_executions) * 100 
      : 0;
    
    const avg_duration_formatted = this.formatDuration(stats.avg_duration);
    
    return {
      ...stats,
      success_rate: Math.round(success_rate * 100) / 100,
      avg_duration_formatted
    };
  }
  
  // 获取执行趋势
  async getExecutionTrends(options: {
    script_id?: string;
    connection_id?: string;
    days?: number;
  } = {}): Promise<Array<{
    date: string;
    total_executions: number;
    successful_executions: number;
    failed_executions: number;
    avg_duration: number;
    success_rate: number;
  }>> {
    const trends = await executionModel.getExecutionTrends(options);
    
    return trends.map(trend => ({
      ...trend,
      success_rate: trend.total_executions > 0 
        ? Math.round((trend.successful_executions / trend.total_executions) * 10000) / 100
        : 0
    }));
  }
  
  // 获取最近执行记录
  async getRecentExecutions(limit: number = 10): Promise<IExecution[]> {
    return await executionModel.getRecentExecutions(limit);
  }
  
  // 清理旧的执行记录
  async cleanupOldExecutions(daysToKeep: number = 90): Promise<{
    deleted_count: number;
    message: string;
  }> {
    if (daysToKeep < 7) {
      throw new Error('保留天数不能少于7天');
    }
    
    const deletedCount = await executionModel.cleanupOldExecutions(daysToKeep);
    
    return {
      deleted_count: deletedCount,
      message: `已清理 ${deletedCount} 条超过 ${daysToKeep} 天的执行记录`
    };
  }
  
  // 获取脚本执行摘要
  async getScriptExecutionSummary(scriptId: string): Promise<{
    script: any;
    stats: ExecutionStats & { success_rate: number };
    recent_executions: IExecution[];
    trends: Array<{
      date: string;
      total_executions: number;
      success_rate: number;
    }>;
  }> {
    // 验证脚本是否存在
    const script = await scriptModel.getScriptWithPath(scriptId);
    if (!script) {
      throw new Error('脚本不存在');
    }
    
    // 获取统计信息
    const stats = await this.getExecutionStats({ script_id: scriptId });
    
    // 获取最近执行记录
    const recentResult = await executionModel.getExecutionHistory(scriptId, { limit: 5 });
    
    // 获取趋势数据
    const trends = await this.getExecutionTrends({ script_id: scriptId, days: 7 });
    
    return {
      script,
      stats,
      recent_executions: recentResult.executions,
      trends: trends.map(t => ({
        date: t.date,
        total_executions: t.total_executions,
        success_rate: t.success_rate
      }))
    };
  }
  
  // 获取连接执行摘要
  async getConnectionExecutionSummary(connectionId: string): Promise<{
    connection: any;
    stats: ExecutionStats & { success_rate: number };
    recent_executions: IExecution[];
    top_scripts: Array<{
      script_id: string;
      script_name: string;
      execution_count: number;
    }>;
  }> {
    // 验证连接是否存在
    const connection = await connectionModel.getConnectionById(connectionId);
    if (!connection) {
      throw new Error('数据库连接不存在');
    }
    
    // 获取统计信息
    const stats = await this.getExecutionStats({ connection_id: connectionId });
    
    // 获取最近执行记录
    const recentResult = await executionModel.getExecutionsByConnection(connectionId, { limit: 5 });
    
    // 获取最常执行的脚本
    const topScriptsResult = await executionModel.raw(
      `SELECT 
        e.script_id,
        s.name as script_name,
        COUNT(*) as execution_count
       FROM executions e
       LEFT JOIN scripts s ON e.script_id = s.id
       WHERE e.connection_id = $1
       GROUP BY e.script_id, s.name
       ORDER BY execution_count DESC
       LIMIT 10`,
      [connectionId]
    );
    
    return {
      connection,
      stats,
      recent_executions: recentResult.executions,
      top_scripts: topScriptsResult.rows.map((row: any) => ({
        script_id: row.script_id,
        script_name: row.script_name || '未知脚本',
        execution_count: parseInt(row.execution_count, 10)
      }))
    };
  }
  
  // 批量取消运行中的执行
  async cancelRunningExecutions(executionIds: string[]): Promise<{
    cancelled_count: number;
    failed_count: number;
    errors: string[];
  }> {
    let cancelledCount = 0;
    let failedCount = 0;
    const errors: string[] = [];
    
    for (const executionId of executionIds) {
      try {
        const result = await this.cancelExecution(executionId);
        if (result) {
          cancelledCount++;
        } else {
          failedCount++;
          errors.push(`执行 ${executionId} 取消失败`);
        }
      } catch (error) {
        failedCount++;
        errors.push(`执行 ${executionId} 取消失败: ${error.message}`);
      }
    }
    
    return {
      cancelled_count: cancelledCount,
      failed_count: failedCount,
      errors
    };
  }
  
  // 格式化执行时间
  private formatDuration(milliseconds: number): string {
    if (milliseconds < 1000) {
      return `${Math.round(milliseconds)}ms`;
    } else if (milliseconds < 60000) {
      return `${Math.round(milliseconds / 1000 * 10) / 10}s`;
    } else if (milliseconds < 3600000) {
      const minutes = Math.floor(milliseconds / 60000);
      const seconds = Math.round((milliseconds % 60000) / 1000);
      return `${minutes}m ${seconds}s`;
    } else {
      const hours = Math.floor(milliseconds / 3600000);
      const minutes = Math.round((milliseconds % 3600000) / 60000);
      return `${hours}h ${minutes}m`;
    }
  }
  
  // 验证执行权限
  async validateExecutionPermission(scriptId: string, connectionId: string, userId?: string): Promise<{
    allowed: boolean;
    reason?: string;
  }> {
    // 检查脚本是否存在
    const script = await scriptModel.findById(scriptId);
    if (!script) {
      return { allowed: false, reason: '脚本不存在' };
    }
    
    // 检查连接是否存在且可用
    const connection = await connectionModel.getConnectionById(connectionId);
    if (!connection) {
      return { allowed: false, reason: '数据库连接不存在' };
    }
    
    if (!connection.is_active) {
      return { allowed: false, reason: '数据库连接已禁用' };
    }
    
    // 检查脚本内容
    if (!script.content || script.content.trim() === '') {
      return { allowed: false, reason: '脚本内容为空' };
    }
    
    // 检查是否有正在运行的相同脚本执行
    const runningExecutions = await executionModel.findAll({
      where: {
        script_id: scriptId,
        connection_id: connectionId,
        status: 'running'
      }
    });
    
    if (runningExecutions.length > 0) {
      return { allowed: false, reason: '该脚本在此连接上已有正在运行的执行' };
    }
    
    return { allowed: true };
  }
}